package pl.umk.mat.fred.unicore.urc.storagemanagement.unicore;

import java.io.IOException;
import java.util.Calendar;
import java.util.List;
import java.util.Map;

import org.w3.x2005.x08.addressing.EndpointReferenceType;

import de.fzj.unicore.rcp.identity.IdentityActivator;
import de.fzj.unicore.uas.client.FileTransferClient;
import de.fzj.unicore.uas.client.RByteIOClient;
import de.fzj.unicore.uas.client.StorageClient;
import de.fzj.unicore.uas.client.TransferControllerClient;
import de.fzj.unicore.uas.util.AddressingUtil;
import de.fzj.unicore.wsrflite.xfire.ClientException;
import de.fzj.unicore.wsrflite.xmlbeans.BaseFault;
import de.fzj.unicore.wsrflite.xmlbeans.WSUtilities;

import org.oasisOpen.docs.wsrf.sg2.EntryType;
import org.unigrids.services.atomic.types.GridFileType;
import org.unigrids.services.atomic.types.ProtocolType;
import org.unigrids.services.atomic.types.ProtocolType.Enum;
import org.unigrids.x2006.x04.services.sms.PermissionsChangeModeType;
import org.unigrids.x2006.x04.services.sms.PermissionsClassType;

public class Storage {
	
	private String url;
	private StorageClient client;
	private Registry registry;
	private String dn = null;
	private String serverVersion = null; 
	private boolean accessDenied;
	
	public Storage(String url, Registry registry) throws Exception {
		this.url = url;
		EndpointReferenceType epr = AddressingUtil.newEPR();
		epr.addNewAddress().setStringValue(url);
		
		client = new StorageClient(epr, IdentityActivator.getDefault().getUASSecProps(url));
		this.registry = registry;
	}
	
	public Storage(EndpointReferenceType ert, String name, Registry registry) throws Exception {
		this.url = ert.getAddress().getStringValue();
		client = new StorageClient(ert, IdentityActivator.getDefault().getUASSecProps(url));
		this.registry = registry;
	}
	
	public Storage(String url, String name) throws Exception {
		this.url = url;
		EndpointReferenceType epr = AddressingUtil.newEPR();
		epr.addNewAddress().setStringValue(url);
		client = new StorageClient(url,epr, IdentityActivator.getDefault().getUASSecProps(url));
	}
	
	public synchronized String getUrl() {
		return url;
	}
	
	public synchronized StorageClient getClient() {
		return client;
	}
	
	public synchronized Registry getRegistry() {
		return registry;
	}
	
	public synchronized void copy(String source, String destination) throws BaseFault {
		if (client != null) {
			client.copy(source, destination);
		}
	}
	
	public synchronized TransferControllerClient fetchFile(String source, String destination) throws Exception {
		if (client != null) {
			return client.fetchFile(source, destination);
		}
		throw new NullPointerException("Storage client is null");
	}
	
	public TransferControllerClient fetchFile(String source,
			String destination, Map<String, String> extraParameters) throws Exception {
		if (client != null) {
			return client.fetchFile(source, destination, extraParameters);
		}
		throw new NullPointerException("Storage client is null");
	}
	
	public synchronized RByteIOClient getImport(String path) throws IOException {
		if (client != null) {
			return client.getImport(path);
		}
		return null;
	}
	
	public synchronized FileTransferClient getImport(String path, Enum ... preferredProtocols) throws IOException {
		if (client != null) {
			return client.getImport(path, preferredProtocols);
		}
		return null;
	}
	
	public synchronized FileTransferClient getImport(String path, boolean append, ProtocolType.Enum proto, Map<String, String> extraParameters) throws IOException {
		if (client != null) {
			return client.getImport(path, append, proto, extraParameters);
		}
		return null;
	}
	
	public synchronized RByteIOClient getExport(String path) throws IOException {
		if (client != null) {
			return client.getExport(path);
		}
		return null;
	}
	
	public synchronized FileTransferClient getExport(String path, Enum ... preferredProtocols) throws IOException {
		if (client != null) {
			return client.getExport(path, preferredProtocols);
		}
		return null;
	}
	
	public synchronized FileTransferClient getExport(String path, ProtocolType.Enum protocol, Map<String, String> extraParameters) throws IOException {
		if (client != null) {
			return client.getExport(path, protocol, extraParameters);
		}
		return null;
	}
	
	public synchronized GridFileType[] listDirectory(String path) throws BaseFault {
		if (client != null) {
			return client.listDirectory(path);
		}
		return null;
	}
	
	public synchronized TransferControllerClient sendFile(String source, String destination) throws Exception {
		if (client != null) {
			return client.sendFile(source, destination);
		}
		return null;
	}
	
	public synchronized void createDirectory(String path) throws BaseFault {
		if (client != null) {
			client.createDirectory(path);
		}
	}
	
	public synchronized void delete(String path) throws BaseFault {
		if (path != null) {
			client.delete(path);
		}
	}
	
	public synchronized void rename(String source, String destination) throws BaseFault {
		if (client != null) {
			client.rename(source, destination);
		}
	}
	
	public synchronized String getStorageName() throws Exception {
		if (client != null) {
			return client.getStorageName();
		}
		return null;
	}
	
	public synchronized String getDN() {
		if (dn == null) {
			try {
				String url2 = url;
				if(url2.contains("/services/")) {
					url2 = url2.substring(0,url2.indexOf("/services"));
				}
				
				List<EntryType> entryTypeList = null;
				synchronized (getRegistry()) {
					entryTypeList = getRegistry().getClient().listEntries();
				}
				if (entryTypeList == null) {
					return null;
				}
				for (EntryType ep : entryTypeList) {
					if(ep.getMemberServiceEPR().getAddress().getStringValue().startsWith(url)){
						String dn2 = WSUtilities.extractServerIDFromEPR(ep.getMemberServiceEPR());
						if ((dn2 != null) && !"".equals(dn2)) {
							dn = dn2;
							return dn;
						}
					}
				}
			} catch (Exception e) {
				return null;
			}
		}
		return dn;
	}
	
	public synchronized Long getAvailableSpace() throws Exception {
		return client.getAvailableSpace();
	}

	public synchronized void setDN(String dn) {
		this.dn = dn;
	}
	
	public synchronized String getName() {
		int start = url.indexOf("/", url.indexOf("://") + 3);
		if (start == -1) {
			return "Storage";
		}
		int end = url.indexOf("/", start + 1);
		if (end == -1) {
			return "Storage";
		}
		return url.substring(start + 1, end);
	}
	
	public synchronized boolean checkConnection() throws ClientException {
		return client.checkConnection();
	}

	public synchronized void setClient(StorageClient client2) {
		client = client2;
	}

	public synchronized void setAccessDenied(boolean b) {
		accessDenied = b;
	}
	
	public synchronized boolean getAccessDenied() {
		return accessDenied;
	}
	
	public synchronized ProtocolType.Enum[] getSupportedProtocols() throws Exception {
		return client.getSupportedProtocols();
	}
	
	public synchronized String getServerVersion() {
		if (serverVersion != null) {
			return serverVersion;
		}
		if (client != null) {
			try {
				serverVersion = client.getServerVersion();
				return serverVersion;
			} catch (Exception e) {
				serverVersion = null;
			}
		}
		return null;
	}
	
	public synchronized void changePermissions(String path, boolean read, boolean write, boolean execute) throws BaseFault {
		if (client == null) {
			return;
		}
		client.changePermissions(path, read, write, execute);
	}
	
	public synchronized void changePermissions2(String path, PermissionsChangeModeType.Enum mode, PermissionsClassType.Enum permClass, String rwxPermissions, boolean recursive) throws BaseFault {
		if (client == null) {
			return;
		}
		client.changePermissions2(path, mode, permClass, rwxPermissions, recursive);
	}
	
	public synchronized GridFileType[] find(String base, boolean recurse, String nameMatch, boolean regexp, Calendar before, Calendar after) throws BaseFault {
		return client.find(base, recurse, nameMatch, regexp, before, after);
	}

}
